package com.itheima.stargraph.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.stargraph.mapper.UserFundMapper;
import com.itheima.stargraph.pojo.UserFund;
import com.itheima.stargraph.pojo.UserFundRecord;
import com.itheima.stargraph.service.IUserFundRecordService;
import com.itheima.stargraph.service.IUserFundService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 用户账户信息表 服务实现类
 * </p>
 *
 * @author mr.wu
 * @since 2025-06-14
 */
@Service
public class UserFundServiceImpl extends ServiceImpl<UserFundMapper, UserFund> implements IUserFundService {

    @Autowired
    private IUserFundRecordService userFundRecordService;

    /**
     * 积分冻结：指从用户积分账户拿出积分，增加到用户积分冻结账户上
     *
     * @param userId 用户id
     * @param score  积分
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void freeze(Long userId, Long score) {
        //1. 查询是否有账户信息
        UserFund userFund = this.lambdaQuery().eq(UserFund::getUserId, userId).one();
        if(userFund==null) {
            throw new RuntimeException("无账户信息");
        }

        //2. 判断积分账户余额是否充足
        if(userFund.getScore()<score) {
            throw new RuntimeException("积分账户积分不足");
        }

        //3. 账户积分变更（积分账户扣减、积分冻结账户增加）
        Long count = this.getBaseMapper().updateForFreeze(userFund.getId(), score);
        if(count<=0) {
            throw new RuntimeException("账户积分变更（积分账户扣减、积分冻结账户增加）失败");
        }

        //4. 账户变更流水记录新增（积分账户扣减记录、积分冻结账户增加记录）
        List<UserFundRecord> userFundRecordList = Arrays.asList(

                //积分账户扣减记录
                UserFundRecord.builder()
                        .fundId(userFund.getId()) //账户id
                        .fundType(0)//积分账户
                        .money(-score)//扣减的积分
                        .build(),

                //积分冻结账户增加记录
                UserFundRecord.builder()
                        .fundId(userFund.getId()) //账户id
                        .fundType(1)//积分冻结账户
                        .money(score) //增加的积分
                        .build()
        );
        boolean result = userFundRecordService.saveBatch(userFundRecordList);
        if(!result) {
            throw new RuntimeException("账户流标记录新增（积分账户扣减记录、积分冻结账户增加记录）失败");
        }

    }

    /**
     * 冻结归还：指从积分冻结账户上拿出积分，增加到用户积分账户上
     *
     * @param userId 用户id
     * @param score  积分
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void refund(Long userId, Long score) {
        //1. 查询是否有账户信息
        UserFund userFund = this.lambdaQuery().eq(UserFund::getUserId, userId).one();
        if(userFund==null) {
            throw new RuntimeException("无账户信息");
        }

        //2. 判断积分账户余额是否充足
        if(userFund.getFreezeScore()<score) {
            throw new RuntimeException("积分冻结账户积分不足");
        }

        //3. 账户积分变更（积分账户增加、积分冻结账户扣减）
        Long count = this.getBaseMapper().updateForRefund(userFund.getId(), score);
        if(count<=0) {
            throw new RuntimeException("账户积分变更（积分账户增加、积分冻结账户扣减）失败");
        }

        //4. 账户变更流水记录新增（积分账户增加记录、积分冻结账户扣减记录）
        List<UserFundRecord> userFundRecordList = Arrays.asList(

                //积分账户增加记录
                UserFundRecord.builder()
                        .fundId(userFund.getId()) //账户id
                        .fundType(0)//积分账户
                        .money(score)//增加的积分
                        .build(),

                //积分冻结账户扣减记录
                UserFundRecord.builder()
                        .fundId(userFund.getId()) //账户id
                        .fundType(1)//积分冻结账户
                        .money(-score) //扣减的积分
                        .build()
        );
        boolean result = userFundRecordService.saveBatch(userFundRecordList);
        if(!result) {
            throw new RuntimeException("账户变更流水记录新增（积分账户增加记录、积分冻结账户扣减记录）失败");
        }
    }

    /**
     * 积分扣除：指从用户积分冻结账号上拿出积分，增加到总账户的积分账户上
     *
     * @param userId 用户id
     * @param score  积分
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deduct(Long userId, Long score) {
        //1. 查询是否有账户信息
        UserFund userFund = this.lambdaQuery().eq(UserFund::getUserId, userId).one();
        if(userFund==null) {
            throw new RuntimeException("无账户信息");
        }

        //2. 判断积分账户余额是否充足
        if(userFund.getFreezeScore()<score) {
            throw new RuntimeException("积分冻结账户积分不足");
        }

        //3. 账户积分变更（积分冻结账户扣减、总账户积分账户增加）
        Long countFreezeScore = this.getBaseMapper().updateFreeScoreDecrement(userFund.getId(), score); //积分冻结账户扣减
        if(countFreezeScore<=0) {
            throw new RuntimeException("账户积分变更（积分冻结账户扣减）失败");
        }

        Long countFreezeTotal = this.getBaseMapper().updateTotalScoreIncrement(score); //总账户积分账户增加
        if(countFreezeTotal<=0) {
            throw new RuntimeException("账户积分变更（总账户积分账户增加）失败");
        }

        //4. 账户变更流水记录新增（积分冻结账户扣减记录、总账户积分账户增加记录）
        List<UserFundRecord> userFundRecordList = Arrays.asList(

                //积分冻结账户扣减记录
                UserFundRecord.builder()
                        .fundId(userFund.getId()) //账户id
                        .fundType(1)//积分冻结账户
                        .money(-score) //扣减的积分
                        .build(),

                //总账积分账户增加记录
                UserFundRecord.builder()
                        .fundId(0L) //账户id
                        .fundType(0)//积分账户
                        .money(score)//增加的积分
                        .build()

        );
        boolean result = userFundRecordService.saveBatch(userFundRecordList);
        if(!result) {
            throw new RuntimeException("账户变更流水记录新增（积分冻结账户扣减记录、总账户积分账户增加记录）失败");
        }
    }

    /**
     * 直接划扣：指从用户的积分账户上拿出积分，增加到总账户的积分账户上
     *
     * @param userId 用户id
     * @param score  积分
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void directDeduct(Long userId, Long score) {
        //1. 查询是否有账户信息
        UserFund userFund = this.lambdaQuery().eq(UserFund::getUserId, userId).one();
        if(userFund==null) {
            throw new RuntimeException("无账户信息");
        }

        //2. 判断积分账户余额是否充足
        if(userFund.getScore()<score) {
            throw new RuntimeException("积分账户积分不足");
        }

        //3. 账户积分变更（积分账户扣减、总账户积分账户增加）
        Long countFreezeScore = this.getBaseMapper().updateScoreDecrement(userFund.getId(), score); //积分账户扣减
        if(countFreezeScore<=0) {
            throw new RuntimeException("账户积分变更（积分账户扣减）失败");
        }

        Long countFreezeTotal = this.getBaseMapper().updateTotalScoreIncrement(score); //总账户积分账户增加
        if(countFreezeTotal<=0) {
            throw new RuntimeException("账户积分变更（总账户积分账户增加）失败");
        }

        //4. 账户变更流水记录新增（积分账户扣减记录、总账户积分账户增加记录）
        List<UserFundRecord> userFundRecordList = Arrays.asList(

                //积分账户扣减记录
                UserFundRecord.builder()
                        .fundId(userFund.getId()) //账户id
                        .fundType(1)//积分账户
                        .money(-score) //扣减的积分
                        .build(),

                //总账积分账户增加记录
                UserFundRecord.builder()
                        .fundId(0L) //账户id
                        .fundType(0)//积分账户
                        .money(score)//增加的积分
                        .build()

        );
        boolean result = userFundRecordService.saveBatch(userFundRecordList);
        if(!result) {
            throw new RuntimeException("账户变更流水记录新增（积分账户扣减记录、总账户积分账户增加记录）失败");
        }
    }
}
